package com.dushuren.project.utils;

import com.dushuren.project.common.ErrorCode;
import com.dushuren.project.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.hash.DecoratingStringHashMapper;
import org.springframework.data.redis.hash.Jackson2HashMapper;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtils {

  @Resource(name = "kryoRedisTemplate")
  private RedisTemplate<String, Object> kryoRedisTemplate;

  private static double size = Math.pow(2, 32);

  /***
   * 写入 缓存
   */
  public boolean setBit(String key, long offset, boolean isShow) {
	boolean result = false;
	try {
	  ValueOperations operations =   kryoRedisTemplate.opsForValue();
	  result = Boolean.TRUE.equals(operations.setBit(key, offset, isShow));
	} catch (Exception e) {
	  throw new BusinessException(ErrorCode.STORAGE_ERROR);
	}
	return result;
  }

  /***
   *  获取 偏移位
   */
  public boolean getBit(String key, long offset) {
	boolean result = false;
	try {
	  ValueOperations operations =   kryoRedisTemplate.opsForValue();
	  result = Boolean.TRUE.equals(operations.getBit(key, offset));
	} catch (Exception e) {
	  throw new BusinessException(ErrorCode.STORAGE_ERROR);
	}
	return result;
  }

  /***
   * 写入 缓存
   */
  public boolean set(final String key, Object value) {
	boolean result = false;
	try {
	  ValueOperations operations =   kryoRedisTemplate.opsForValue();
	  operations.set(key, value);
	  result = true;
	} catch (Exception e) {
	  throw new BusinessException(ErrorCode.STORAGE_ERROR);
	}
	return result;
  }

  /**
   * 写入缓存设置时效时间
   */
  public boolean set(String key, Object value, Long expireTime) {
	boolean result = false;
	try {
	  kryoRedisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
	  result = true;
	} catch (Exception e) {
	  e.printStackTrace();
	  throw new BusinessException(ErrorCode.STORAGE_ERROR);
	}
	return result;
  }

  /**
   * 批量删除对应的value
   */
  public void remove(final String... keys) {
	for (String key : keys) {
	  remove(key);
	}
  }

  /**
   * 删除对应的value
   */
  public void remove(final String key) {
	if (exists(key)) {
	    kryoRedisTemplate.delete(key);
	}
  }

  /**
   * 判断缓存中是否有对应的value
   */
  public boolean exists(final String key) {
	return   kryoRedisTemplate.hasKey(key);
  }
  /**
   * 读取缓存
   */
  public Object get(final String key) {
	Object result = null;
	ValueOperations operations =   kryoRedisTemplate.opsForValue();
	result = operations.get(key);
	return result;
  }

  /**
   * 哈希添加
   */
  public void hmSet(String key, Object hashKey, Object value) {
	HashOperations<String, Object, Object> hash =   kryoRedisTemplate.opsForHash();
	hash.put(key, hashKey, value);
  }

  /**
   * 哈希获取数据
   */
  public Object hmGet(String key, Object hashKey) {
	HashOperations<String, Object, Object> hash =   kryoRedisTemplate.opsForHash();
	return hash.get(key, hashKey);
  }

  /**
   * 列表添加
   */
  public void lPush(String k, Object v) {
	ListOperations<String, Object> list =   kryoRedisTemplate.opsForList();
	list.rightPush(k, v);
  }

  /**
   * 列表获取
   */
  public List<Object> lRange(String k, long l, long l1) {
	ListOperations<String, Object> list =   kryoRedisTemplate.opsForList();
	return list.range(k, l, l1);
  }

  /**
   * 集合添加
   */
  public void add(String key, Object value) {
	SetOperations<String, Object> set = kryoRedisTemplate.opsForSet();
	set.add(key, value);
  }

  /**
   * 集合获取
   */
  public Set<Object> setMembers(String key) {
	SetOperations<String, Object> set =   kryoRedisTemplate.opsForSet();
	return set.members(key);
  }

  /**
   * 有序集合添加
   */
  public void zAdd(String key, Object value, double scoure) {
	ZSetOperations<String, Object> zset =   kryoRedisTemplate.opsForZSet();
	zset.add(key, value, scoure);
  }

  /**
   * 有序集合获取
   */
  public Set<Object> rangeByScore(String key, double scoure, double scoure1) {
	ZSetOperations<String, Object> zset =   kryoRedisTemplate.opsForZSet();
	  kryoRedisTemplate.opsForValue();
	return zset.rangeByScore(key, scoure, scoure1);
  }


  /**
   * 有序集合获取排名
   *
   * @param key 集合名称
   * @param value 值
   */
  public Long zRank(String key, Object value) {
	ZSetOperations<String, Object> zset =   kryoRedisTemplate.opsForZSet();
	return zset.rank(key,value);
  }


  /**
   * 有序集合获取排名
   */
  public Set<ZSetOperations.TypedTuple<Object>> zRankWithScore(String key, long start,long end) {
	ZSetOperations<String, Object> zset =   kryoRedisTemplate.opsForZSet();
	Set<ZSetOperations.TypedTuple<Object>> ret = zset.rangeWithScores(key,start,end);
	return ret;
  }

  /**
   * 获取集合中key、value元素对应的score值
   */
  public Double zSetScore(String key, Object value) {
	ZSetOperations<String, Object> zset =   kryoRedisTemplate.opsForZSet();
	return zset.score(key,value);
  }


  /**
   * 有序集合添加分数
   */
  public void incrementScore(String key, Object value, double scoure) {
	ZSetOperations<String, Object> zset =   kryoRedisTemplate.opsForZSet();
	zset.incrementScore(key, value, scoure);
  }


  /**
   * 有序集合获取排名
   */
  public Set<ZSetOperations.TypedTuple<Object>> reverseZRankWithScore(String key, long start,long end) {
	ZSetOperations<String, Object> zset =   kryoRedisTemplate.opsForZSet();
	Set<ZSetOperations.TypedTuple<Object>> ret = zset.reverseRangeByScoreWithScores(key,start,end);
	return ret;
  }

  /**
   * 有序集合获取排名
   */
  public Set<ZSetOperations.TypedTuple<Object>> reverseZRankWithRank(String key, long start, long end) {
	ZSetOperations<String, Object> zset =   kryoRedisTemplate.opsForZSet();
	Set<ZSetOperations.TypedTuple<Object>> ret = zset.reverseRangeWithScores(key, start, end);
	return ret;
  }

  /**
   * hash putAll存储
   * 存储对象
   */
  public void hashPutAll(String key, Object object){
	HashOperations hashOperations = kryoRedisTemplate.opsForHash();
	hashOperations.putAll(key, new DecoratingStringHashMapper<>(new Jackson2HashMapper(true)).toHash(object));
  }

  /**
   * hash 获取对象
   */
  public Object getHashPut(String key){
	HashOperations hashOperations = kryoRedisTemplate.opsForHash();
	Object o = new Jackson2HashMapper(true).fromHash(hashOperations.entries(key));
	return o;
  }
}
